﻿using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
using MentalAlchemy.Atomics;
using MentalAlchemy.Molecules;

namespace VectorAnalysis
{
	public partial class MainForm : Form
	{
		public MainForm()
		{
			InitializeComponent();
		}

		private void VarBtn_Click(object sender, EventArgs e)
		{
			if (dataTableControl1.DataRows.Count == 0) return;

			var m = MatrixMath.CreateFromStringsList(dataTableControl1.DataRows);
			var rows = MatrixMath.ConvertToRowsList(m);
			var var = VectorMath.Variance(rows);
			VarBox.Text = var.ToString();
		}

		private void MeanVectorBtn_Click(object sender, EventArgs e)
		{
			if (dataTableControl1.DataRows.Count == 0) return;

			var m = MatrixMath.CreateFromStringsList(dataTableControl1.DataRows);
			var rows = MatrixMath.ConvertToRowsList(m);
			var meanV = VectorMath.MeanVector(rows);
			var meanVStr = VectorMath.ConvertToStringsArray(meanV.ToArray());

			string resStr = meanVStr[0];
			for (int i = 1; i < meanVStr.Length; i++)
			{
				resStr += "\t" + meanVStr[i];
			}
			MeanVectorBox.Text = resStr;
		}

		private void TestOrthoBasisBtn_Click(object sender, EventArgs e)
		{
			if (dataTableControl1.DataRows.Count == 0) return;

			var m = MatrixMath.CreateFromStringsList(dataTableControl1.DataRows);
			var rows = MatrixMath.ConvertToRowsList(m);
			var basis = MentalAlchemy.Molecules.Numerics.GetOrthonormalBasisPerp(rows[0]);

			//
			// check basis by checking the assumption that pair-wise multiplication yields the identity matrix.
			basis.Add(rows[0]);
			var size = basis.Count;
			var dProds = new float[size,size];
			for (int i = 0; i < size; i++)
			{
				dProds[i, i] = VectorMath.DotProduct(basis[i],basis[i]);
				for (int j = i+1; j < size; j++)
				{
					dProds[i, j] = dProds[j, i] = VectorMath.DotProduct(basis[i], basis[j]);
				}
			}

			var identity = MatrixMath.Identity(basis.Count);
			var sub = MatrixMath.Sub(identity, dProds);
			if (!MatrixMath.IsZero(sub))
			{
				MessageBox.Show("Orthonormal basis creation failed!");
			}
		}

		private void TestDistBtn_Click(object sender, EventArgs e)
		{	// tests calculaiton of the distance between line and the point.
			const int count = 1000;
			var rand = new Random();
			var res = new float[count,2];
			for (int i = 0; i < count; ++i )
			{
				var pt1 = VectorMath.CreateRandomVector(rand, 2, -1, 1);	// 1st point for line.
				var pt2 = VectorMath.CreateRandomVector(rand, 2, -1, 1); // 2nd point for line.
				var pt = VectorMath.CreateRandomVector(rand, 2, -1, 1);
				
				// calculate distace using general formulae for arbitrary dimensions.
				var dist = Numerics.CalculateDistance(pt1, pt2, pt);
				res[i, 0] = dist;

				// calculate distance for 2D explicitly.
				var dist2d = Numerics.CalculateDistance2D(pt1, pt2, pt);
				res[i, 1] = dist2d;
			}

			FileIO.WriteColumns("disttest.log", res, "General\t2D");
		}
	}
}
